<template>
  <div class="pro-test content">
    <div class="fill">
      <el-radio-group v-model="type" size="mini" plain class="radio-group">
        <el-radio-button
          label="0"
          v-if="
            projectType === 'data_predict' || projectType === 'txt_classify'
          "
          >数据</el-radio-button
        >
        <!-- <el-radio-button label="1">JSON</el-radio-button> -->
        <el-radio-button label="2">文件上传</el-radio-button>
      </el-radio-group>
      <div v-show="type == 0" class="radio-panel">
        <div class="tab-panel">
          <div
            v-for="(value, key, index) in predictJson"
            :key="index"
            class="input-suffix"
          >
            <label class="el-form-item__label">{{ key }} :</label>
            <div class="el-form-item__content">
              <el-input v-model="predictJson[key]" />
            </div>
            <div class="el-form-item__error">
              {{ validData(predictJson[key]) }}
            </div>
          </div>
        </div>
        <div class="text-align-center margin-top-10">
          <el-button
            size="mini"
            class="btn"
            @click="toTestObject"
            :disabled="showYcBtn"
            >预测</el-button
          >
        </div>
      </div>
      <div v-show="type == 1" class="radio-panel">
        <div class="tab-title">请在下方输入<span>JSON</span></div>

        <el-input
          type="textarea"
          :autosize="false"
          resize="none"
          class="tab-panel margin-top-10"
          v-model="textarea"
        >
        </el-input>
        <div class="text-align-center margin-top-10">
          <el-button size="mini" class="btn" @click="toTestTextarea"
            >预测</el-button
          >
        </div>
      </div>
      <div v-show="type == 2" class="radio-panel">
        <div class="tab-panel">
          <div class="tab-title" style="text-align: center">
            <!-- 支持上传.txt、.csv、.xls、.xlsx格式文件 -->
            支持上传{{ getAcceptDataType().replace(/,/g, '、')}}
            <el-button type="text" icon="el-icon-download" @click="downloadTpl"
              >下载模板</el-button
            >
          </div>
          <div v-if="!showResult">
            <el-upload
              class="upload-demo"
              action=""
              drag
              ref="upload"
              :file-list="fileList"
              :auto-upload="false"
              :on-change="onChange"
              :show-file-list="false"
              :accept="getAcceptDataType()"
              :multiple="false"
            >
              <div v-if="file ? false : true" v-loading="loading">
                <i class="el-icon-upload"></i>
                <div class="el-upload__text">
                  选择或拖放数据文件
                  <div>支持上传{{ getAcceptDataType().replace(/,/g, '、')}}</div>
                </div>
              </div>
              <div v-else class="file" v-loading="loading">
                <i class="el-icon-document"></i>
                <div>{{ file.name }}</div>
                <div>{{ file.size }}KB</div>
                <i
                  class="el-icon-close"
                  @click="closeFile"
                  title="移除文件"
                ></i>
              </div>
            </el-upload>
          </div>
          <div v-else class="test-result">
            <div v-if="testSuc">
              <i class="el-icon-success"></i>
              <div class="text">预测成功</div>
              <div class="link" @click="getUrl">点解下载预测结果</div>
            </div>
            <div v-else>
              <i class="el-icon-error"></i>
              <div class="text">预测失败</div>
            </div>
          </div>
        </div>
        <div class="text-align-center margin-top-10">
          <el-button
            size="mini"
            class="btn"
            :disabled="disabledFile"
            @click="toTestFile"
            v-if="!showResult"
            >预测</el-button
          >
          <el-button size="mini" class="btn" @click="reUpload" v-else
            >重新上传</el-button
          >
        </div>
      </div>
    </div>
    <div v-show="type < 2" class="forecast">
      <div class="tab-title" style="line-height: 28px">预测结果</div>
      <div class="tab-panel code-panel">
        <pre class="code">{{ data }}</pre>
      </div>
    </div>
  </div>
</template>
<script>
import request from '@/modules/index/utils/request';
import { downloadFile } from '@/utils/common';
import _ from 'lodash';
export default {
  name: 'proTest',
  data() {
    return {
      type: 0,
      textarea: '',
      projectId: '',
      projectType: '',
      publishTask: null,
      data: null,
      predictJson: {},
      showFileResult: false,
      file: null,
      showResult: false,
      testSuc: false,
      urlId: '',
      loading: false,
    };
  },
  created: function () {
    let query = this.$router.currentRoute.query;
    this.projectId = query.id;
    this.projectType = query.type;
    if (!query.id) {
      this.$message.error('无参数传入！');
      this.$router.push({
        path: '/prolist',
      });
    }
    this.init(this.projectType);
  },
  methods: {
    getAcceptDataType: function () {
      let result = '.txt,.csv,.xls,.xlsx,.zip';
      const dataType = this.projectType;
      if (
        ['img_classify', 'voice_classify', 'img_detection'].includes(dataType)
      ) {
        result = '.zip';
      } else if (
        ['data_predict', 'txt_classify', 'data_unsupervised'].includes(dataType)
      ) {
        result = '.txt,.csv,.xls,.xlsx,';
      }
      return result;
    },
    async init(projectType) {
      // let projectId=this.projectId;
      let publishTask = null;
      try {
        publishTask = await this.loadPublishTask();
      } catch (err) {
        return;
      }
      this.publishTask = publishTask;
      if (projectType != 'data_predict' && projectType != 'txt_classify') {
        this.type = 2;
        return;
      }

      let predictJson = null;
      try {
        predictJson = await this.loadPredictJson();
      } catch (err) {
        return;
      }
      this.predictJson = predictJson;
      this.textarea = JSON.stringify(predictJson);
    },
    loadPublishTask() {
      let projectId = this.projectId;
      return new Promise((resolve, reject) => {
        request({
          url: '/publishtask/publish-task-data/search', //接口
          method: 'GET',
          params: { page: 1, pageSize: 1, projectId: projectId },
        })
          .then((res) => {
            if (res.data.success) {
              if (res.data.data.list.length > 0) {
                resolve(res.data.data.list[0]);
              }
              resolve(null);
            } else {
              this.$message.error(res.data.msg);
              reject(res.data.msg);
            }
          })
          .catch((err) => {
            this.$message.error('获取失败！');
          });
      });
    },
    loadPredictJson() {
      let publishTaskId = this.publishTask.id;

      return new Promise((resolve, reject) => {
        request({
          url: `/publishtask/publish-task-data/${publishTaskId}/get-predict-json`, //接口
          method: 'POST',
        })
          .then((res) => {
            if (res.data.success) {
              if (res.data.data.length > 0) {
                resolve(res.data.data[0]);
              }
              reject(null);
            } else {
              this.$message.error(res.data.msg);
              reject(res.data.msg);
            }
          })
          .catch((err) => {
            this.$message.error('获取失败！');
          });
      });
    },
    toTestObject() {
      let predictJson = this.predictJson;
      //项目类型为数据预测的json的value必为数据，如果后端修改则可删除
      if (this.projectType === 'data_predict') {
        predictJson = _.mapValues(predictJson, function (value) {
          return _.toNumber(value) || 0;
        });
      }

      this.toTest([predictJson]);
    },
    toTestTextarea() {
      let textarea = this.textarea;
      if (!this.isJSON(textarea)) {
        this.$message.error('输入结果并不是json数据！');
        return;
      }
      textarea = JSON.parse(textarea);
      this.toTest(textarea);
    },
    isJSON(str) {
      if (typeof str == 'string') {
        try {
          var obj = JSON.parse(str);
          if (typeof obj == 'object' && obj) {
            return true;
          } else {
            return false;
          }
        } catch (e) {
          console.log('error：' + str + '!!!' + e);
          return false;
        }
      }
    },
    toTest(jsonList) {
      let publishTaskId = this.publishTask.id;
      let data = {
        predictData: jsonList,
      };
      // data=_.mapKeys(data, function(value, key) { return '"'+key+'"' });
      request({
        url: `/publishtask/publish-task-data/${publishTaskId}/predict-data`, //接口
        method: 'POST',
        data: data,
      })
        .then((res) => {
          if (res.data.success) {
            this.data = res.data.data;
          } else {
            this.$message.error(res.data.msg);
          }
        })
        .catch((err) => {
          this.$message.error('获取失败！');
        });
    },
    onChange(files, fileList) {
      this.file = files;
    },
    closeFile(e) {
      e.stopPropagation();
      this.file = null;
    },
    async toTestFile() {
      this.loading = true;
      let fileInfo = null;
      this.$confirm('是否跳转至我的预测列表?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.$router.push('/forecastList');
        })
        .catch(() => {});
      try {
        fileInfo = await this.uploadFile();
      } catch (err) {
        this.loading = false;
        return;
      }

      let fileInfo2 = null;
      try {
        fileInfo2 = await this.createByFile(fileInfo);
      } catch (err) {
        this.loading = false;
        return;
      }
      let fileResult = false;
      try {
        this.showResult = true;
        fileResult = await this.runByFile(fileInfo, fileInfo2);
      } catch (err) {
        fileResult = false;
      }
      this.showResult = true;
      this.testSuc = fileResult;
      if (fileResult) {
        this.urlId = fileInfo2.id;
      }
      this.loading = false;
    },
    uploadFile() {
      let projectId = this.projectId;
      if (!projectId) {
        this.$message.error('没有项目ID');
      }
      let formData = new FormData();
      formData.append('File', this.file.raw);
      formData.append('projectId ', projectId);
      return new Promise((resolve, reject) => {
        request({
          url: `material-info/upload`, //接口
          method: 'post',
          data: formData,
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        })
          .then((res) => {
            let result = res.data;
            if (!result.success) {
              this.$message.error(result.msg);
              reject(result.msg);
            } else {
              resolve(result.data);
            }
          })
          .catch((err) => {
            this.$message.error('项目保存失败！');
            reject(err);
          });
      });
    },
    createByFile(fileInfo) {
      let publishTask = this.publishTask,
        id = publishTask.id;
      let data = fileInfo;

      return new Promise((resolve, reject) => {
        request({
          url: `/publishtask/publish-task-data/${id}/predict-data-multi-create`, //接口
          method: 'POST',
          data: data,
        })
          .then((res) => {
            let result = res.data;
            if (!result.success) {
              this.$message.error(result.msg);
              reject(result.msg);
            } else {
              resolve(result.data);
            }
          })
          .catch((err) => {
            this.$message.error('项目保存失败！');
            reject(err);
          });
      });
    },
    runByFile(fileInfo, fileInfo2) {
      let publishTask = this.publishTask,
        id = publishTask.id;
      let data = fileInfo;
      data.id = fileInfo2.id;
      return new Promise((resolve, reject) => {
        request({
          url: `/publishtask/publish-task-data/${id}/predict-data-multi`, //接口
          method: 'POST',
          data: data,
        })
          .then((res) => {
            let result = res.data;
            if (!result.success) {
              this.$message.error(result.msg);
              reject(result.msg);
            } else {
              resolve(result.data);
            }
          })
          .catch((err) => {
            this.$message.error(err);
            reject(err);
          });
      });
    },
    reUpload() {
      this.showResult = false;
      this.file = null;
    },
    validData(value) {
      if (value === null || value === '') {
        return '不能为空！';
      }
      let projectType = this.projectType;
      if (projectType === 'data_predict') {
        if (_.isNaN(_.toNumber(value))) {
          return '只能填数字';
        }
      }

      return '';
    },
    getPredictTask() {
      let publishTask = this.publishTask,
        id = publishTask.id;
      return new Promise((resolve, reject) => {
        request({
          url: `/predicttask/predict-task/findByPublishId/${id}`, //接口
          method: 'GET',
          params: { publishId: id },
        })
          .then((res) => {
            let result = res.data;
            if (!result.success) {
              this.$message.error(result.msg);
              reject(result.msg);
            } else {
              resolve(result.data);
            }
          })
          .catch((err) => {
            this.$message.error(err);
            reject(err);
          });
      });
    },
    getUrl() {
      let id = this.urlId;
      request({
        url: `/predicttask/predict-task/${id}/getResultUrl`, //接口
        method: 'GET',
        params: { id: id },
        responseType: 'blob',
      })
        .then((response) => {
          if (!response.data) {
            this.$message.error('下载文件失败');
            return;
          }
          downloadFile(response);
        })
        .catch((err) => {
          this.$message.error(err);
        });
    },
    downloadTpl() {
      let fileType = this.projectType;
      if (!fileType) {
        this.$message.error('无文件类型传入！');
      }

      request({
        url: '/material-info/getUrl', //接口
        method: 'post',
        params: { projectType: fileType },
        responseType: 'blob',
      }).then((response) => {
        if (!response.data) {
          this.$message.error('下载文件失败');
          return;
        }
        downloadFile(response);
      });
    },
  },
  computed: {
    fileList: function () {
      var file = this.file;
      if (!file) {
        return [];
      }
      return [file];
    },
    disabledFile: function () {
      var file = this.file;
      if (file) {
        return false;
      }
      return true;
    },
    showYcBtn: function () {
      let json = this.predictJson,
        result = false,
        projectType = this.projectType;
      if (!json) {
        return result;
      }
      _.mapKeys(json, (item) => {
        if (item === null || item === '') {
          result = true;
        }
        if (projectType === 'data_predict') {
          if (_.isNaN(_.toNumber(item))) {
            result = true;
          }
        }
      });
      return result;
    },
  },
};
</script>
<style scoped>
.el-textarea >>> .el-textarea__inner {
  border: 0px solid #dcdfe6;
  height: 100%;
  /* resize: none; */
}
.upload-demo >>> .el-upload {
  width: 60%;
}
.upload-demo >>> .el-upload .el-upload-dragger {
  width: 100%;
}
</style>
<style lang="less" scoped>
@import '~@/style/variables.less';

.pro-test {
  height: 100%;
  margin-bottom: 0px;
  display: flex;
  flex-wrap: wrap;
}
.radio-group {
  margin-bottom: 10px;
}
.el-radio-button__inner {
  background: #ecf5ff;
}
.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled) {
  box-shadow: none;
}
.fill {
  flex: 1;
  display: flex;
  min-width: 60%;
  flex-direction: column;
}
.forecast {
  width: 40%;
  min-width: 200px;
  flex: none;
  padding: 10px 7px 0px 10px;
}
.tab-title {
  font-size: 14px;
  span {
    color: @--color-primary;
    margin-left: 10px;
  }
}
.tab-panel {
  width: 100%;
  border: 0.5px solid #ccc;
  flex: 1;
}
.margin-top-10 {
  margin-top: 10px;
}
.text-align-center {
  text-align: center;
}
.radio-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.btn {
  padding: 5px 30px;
}
.btn:not(.is-disabled) {
  border-color: @--color-primary;
  color: @--color-primary;
}
.code-panel {
  height: calc(100% - 28px);
  max-height: calc(100% - 28px);
  overflow-y: scroll;
  overflow-x: hidden;
  box-sizing: border-box;
}
.code {
  padding: 0px 10px;
  box-sizing: border-box;
}
.el-textarea {
  /deep/ textarea {
    border: 0px solid #dcdfe6;
    height: 100%;
    resize: none;
  }
}
.upload-demo {
  text-align: center;
}
.input-suffix {
  display: flex;
  margin-bottom: 22px;
  justify-content: center;
  position: relative;
  flex-wrap: wrap;
  .el-form-item__label {
    width: 150px;
  }
  &:first-of-type {
    margin-top: 22px;
  }
  .el-form-item__error {
    position: relative;
    vertical-align: middle;
    box-sizing: border-box;
    width: 100%;
    text-align: center;
  }
}
.file {
  position: relative;
  display: flex;
  width: 100%;
  height: 100%;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  i {
    color: @--color-primary;
    font-size: 50px;
  }
  div {
    font-size: 14px;
    line-height: 18px;
    color: #000;
  }
  .el-icon-close {
    position: absolute;
    font-size: 16px;
    color: #000;
    top: 10px;
    right: 10px;
    cursor: pointer;
  }
}
.test-result {
  width: 100%;
  text-align: center;
  position: relative;
  & > div {
    position: relative;
    width: 60%;
    margin: auto;
    min-width: 300px;
    min-height: 200px;
    border: 1px dashed @--color-primary;
    border-radius: 6px;
    box-sizing: border-box;
    i {
      margin-top: 30px;
      font-size: 65px;
      &.el-icon-success {
        color: green;
      }
      &.el-icon-error {
        color: red;
      }
    }
    .text {
      font-size: 13px;
      line-height: 20px;
    }
    .link {
      font-size: 13px;
      cursor: pointer;
      line-height: 20px;
    }
    .overflow-scroll {
      position: relative;
      max-height: 200px;
      overflow-y: auto;
      margin-bottom: 20px;
    }
  }
}
</style>
